package cn.buk.api.azure;

import com.azure.storage.blob.*;
import com.azure.storage.blob.models.BlobItem;
import com.azure.storage.blob.models.BlobProperties;
import com.azure.storage.blob.sas.BlobServiceSasSignatureValues;

import java.io.InputStream;
import java.time.*;
import java.util.ArrayList;
import java.util.List;

public class BlobServiceImpl implements BlobService {

  private final String accountName;

  private final String accountKey;

  private final String endPointSuffix;

  public BlobServiceImpl(String accountName, String accountKey, String endPointSuffix) {
    this.accountName = accountName;
    this.accountKey = accountKey;
    this.endPointSuffix = endPointSuffix;


  }

  /**
   * Azure存储链接字符串
   * AZURE_STORAGE_CONNECTION_STRING
   *
   * @return
   */
  private String getConnectionStr() {
    return "DefaultEndpointsProtocol=https;"
            + "AccountName=" + this.accountName + ";"
            + "AccountKey=" + this.accountKey + ";"
            + "EndpointSuffix=" + this.endPointSuffix + ";";
  }

  private BlobServiceClient blobServiceClient;

  private BlobServiceClient getBlobServiceClient() {
    synchronized (this) {
      if (blobServiceClient == null) {
        // Create a BlobServiceClient object which will be used to create a container client
        blobServiceClient = new BlobServiceClientBuilder().connectionString(getConnectionStr()).buildClient();
      }
      return blobServiceClient;
    }
  }

  @Override
  public int createContainer(String containerName) {
    try {
      if (getBlobServiceClient().getBlobContainerClient(containerName).exists()) {
        return 0;
      } else {
        getBlobServiceClient().createBlobContainer(containerName);
        return 1;
      }
    } catch (Exception ex) {
      ex.getMessage();
      return -1;
    }
  }

  @Override
  public List<String> listContainerNames() {
    List<String> names = new ArrayList<>();

    getBlobServiceClient().listBlobContainers().forEach(t -> {
      names.add(t.getName());
    });

    return names;
  }

  @Override
  public List<String> listContainerBlobs(final String containerName) {
    List<String> items = new ArrayList<>();

    // Create the container and return a container client object
    BlobContainerClient containerClient = getBlobServiceClient().getBlobContainerClient(containerName);

    //检查该容器是否存在
    if (!containerClient.exists()) {
      return items;
    }

    for (BlobItem blobItem : containerClient.listBlobs()) {
      //长度为0的BlobItem是目录
      if (blobItem.getProperties().getContentLength() == 0) {
        //目录
        continue;
      }

      items.add(blobItem.getName());
    }

    return items;
  }

  @Override
  public String generateBlobUrlWithSas(String containerName, String blobName, String identifier) {

    //TODO 暂时无法给某一资源生成SAS，需要改进
    // Create the container and return a container client object
    BlobContainerClient containerClient = getBlobServiceClient().getBlobContainerClient(containerName);

    //使用指定的访问策略标识符
    BlobServiceSasSignatureValues sv = new BlobServiceSasSignatureValues(identifier);
    String sasToken = containerClient.generateSas(sv);
    return String.format("https://%s.blob.core.chinacloudapi.cn/%s/%s?%s", accountName, containerName, blobName, sasToken);
  }

  @Override
  public String uploadLocalFile(String containerName, String localFileName, String blobName) {
    BlobContainerClient containerClient = getBlobServiceClient().getBlobContainerClient(containerName);

    blobName = getBlobName(localFileName, blobName);

    // Get a reference to a blob
    BlobClient blobClient = containerClient.getBlobClient(blobName);

    // Upload the blob
    blobClient.uploadFromFile(localFileName);

    return blobName;
  }

  private String getBlobName(String localFileName, String blobName) {
    if (blobName == null) {
      int lastIndexOf = localFileName.lastIndexOf(".");
      String suffix = localFileName.substring(lastIndexOf);

      LocalDate localDate = LocalDate.now();
      blobName = localDate.getYear() + "/" + localDate.getMonthValue() + "/" + LocalTime.now().toNanoOfDay() + suffix;
    }

    return blobName;
  }

  @Override
  public String uploadLocalFile(String containerName, String localFileName) {
    return uploadLocalFile(containerName, localFileName, null);
  }

  @Override
  public String uploadUrlFile(String containerName, String url, String blobName) {
    BlobContainerClient containerClient = getBlobServiceClient().getBlobContainerClient(containerName);

    blobName = getBlobName(url, blobName);

    BlobClient blobClient = containerClient.getBlobClient(blobName);


    blobClient.copyFromUrl(url);

    return blobName;
  }

  @Override
  public String uploadUrlFile(String containerName, String url) {
    return uploadUrlFile(containerName, url, null);
  }

  @Override
  public String uploadInputStream(String containerName, InputStream inputStream, long length, String blobName) {
    BlobContainerClient containerClient = getBlobServiceClient().getBlobContainerClient(containerName);

    BlobClient blobClient = containerClient.getBlobClient(blobName);


    blobClient.upload(inputStream, length);

    return blobName;
  }

  @Override
  public BlobProperties downloadFile(String containerName, String blobName, String fileName) {
    // Get a reference to a blob
    BlobContainerClient containerClient = getBlobServiceClient().getBlobContainerClient(containerName);

    BlobClient blobClient = containerClient.getBlobClient(blobName);
    return blobClient.downloadToFile(fileName, true);
  }

}
